package org.nabc.generate.mapper.xml;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.nabc.configuration.FileConfiguration;
import org.nabc.constant.ModeConstant;
import org.nabc.constant.TypeConstant;
import org.nabc.generate.AbstractRunnableTask;
import org.nabc.support.PropertyValue;
import org.nabc.support.PropertyValues;

import java.io.IOException;

@Slf4j
public class MybatisMapperXmlTemplateGenerate extends AbstractRunnableTask {
    private static String insertTemplate;
    private static String updateTemplate;
    private static String selectTemplate;

    @Override
    public void setParameters(FileConfiguration fileConfiguration, PropertyValues propertyValues) {
        this.fileSuffix = "xml";
        fileTemplateData = inputFromFile("src/main/resources/template/mybatis/mapper/xml/MapperXml.template");

        String[] strings = getTemplate("#\\[[\\W*\\w*]{0,}?\\]#", fileTemplateData.toString());

        insertTemplate = strings[0];
        updateTemplate = strings[1];
        selectTemplate = strings[2];

        super.setParameters(fileConfiguration, propertyValues, "xml");
    }

    @Override
    public void setModelAndType() {
        this.type = TypeConstant.MAPPER_XML;
        this.mode = ModeConstant.MYBATIS;
    }

    @SneakyThrows
    @Override
    public void generate() {
        String xmlFileData = fileTemplateData.toString()
                .replace("#[" + insertTemplate + "]#", insertSql(propertyValues))
                .replace("#[" + updateTemplate + "]#", updateSql(propertyValues))
                .replace("#[" + selectTemplate + "]#", selectSql(propertyValues))
                .replace("#{primitiveTableName}", propertyValues.getPrimitiveTableName())
                .replace("#{packageName}", fileConfiguration.getPackageName())
                .replace("#{entityClass}", entityName)
                .replace("#{entityName}", lowerLetter(entityName))
                .replace("#{columnName}", lowerLetter(entityName));

        outputToFile(xmlFileData, filePath);
    }

    private String insertSql(PropertyValues propertyValues) {
        StringBuffer insertColumnName = new StringBuffer();
        StringBuffer insertColumnValue = new StringBuffer();

        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
            if (propertyValue.isPrimaryKey()
                    || propertyValue.getColumnName().equals("createTime")
                    || propertyValue.getColumnName().equals("updateTime")
                    || propertyValue.getColumnName().equals("isDelete")) {
                continue;
            }

            insertColumnName.append(propertyValue.getPrimitiveColumnName()).append(",");
            insertColumnValue.append("#{").append(propertyValue.getColumnName()).append("},");
        }

        if (propertyValues.getTableName().equals("Commodity_sku_and_type")) {
            System.out.println();
        }

        insertColumnName.delete(insertColumnName.length() - 1, insertColumnName.length());
        insertColumnValue.delete(insertColumnValue.length() - 1, insertColumnValue.length());

        return insertTemplate
                .replace("#{columnName}", insertColumnName)
                .replace("#{columnValue}", insertColumnValue);
    }

    private String updateSql(PropertyValues propertyValues) {
        StringBuffer updateSql = new StringBuffer();

        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
            if (propertyValue.isPrimaryKey()
                    || propertyValue.getColumnName().equals("createTime")
                    || propertyValue.getColumnName().equals("updateTime")
                    || propertyValue.getColumnName().equals("isDelete")) {
                continue;
            }

            updateSql
                    .append(updateTemplate
                            .replace("#{columnValue}", propertyValue.getColumnName())
                            .replace("#{entityName}", lowerLetter(conversionHump(propertyValues.getTableName())))
                            .replace("#{columnName}", propertyValue.getPrimitiveColumnName()))
                    .append("\n");
        }

        return updateSql.toString();
    }

    private String selectSql(PropertyValues propertyValues) {
        StringBuffer selectSql = new StringBuffer();

        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
            if (propertyValue.isPrimaryKey()
                    || propertyValue.getColumnName().equals("createTime")
                    || propertyValue.getColumnName().equals("updateTime")
                    || propertyValue.getColumnName().equals("isDelete")) {
                continue;
            }

            selectSql
                    .append(selectTemplate
                            .replace("#{columnValue}", propertyValue.getColumnName())
                            .replace("#{entityName}", lowerLetter(conversionHump(propertyValues.getTableName())))
                            .replace("#{columnName}", propertyValue.getPrimitiveColumnName()))
                    .append("\n");
        }

        return selectSql.toString();
    }
}
